import os
import queue
import ctypes
# import json


class FileOpt:
    def __init__(self, path, num, prefix, ext, opt="a+"):
        self.path = path
        self.num = num
        self.prefix = prefix
        self.ext = ext
        self.fs = open("%s/%s_%s.%s" % (path, prefix, num, ext), opt)

    def tell(self):
        return self.fs.tell()

    def seek(self, index):
        self.fs.seek(index)

    def write(self, data):
        self.fs.write(data)

    def write_str(self, data, encode="utf-8"):
        data_bytes = data.encode(encode)
        self.write(data_bytes)

    def close(self):
        self.fs.flush()
        self.fs.close()


class CacheIndex:
    def __init__(self, index_dir, index_file_max=65535, single_file=65535):
        self.index_file_max = index_file_max
        self.single_file = single_file
        self.index_dir = index_dir
        self.mem_file = ctypes.LibraryLoader("/root/projects/MemoryFile/memoryfile.so")
        self.init()

    def init(self):
        index_dir = "%s/index" % self.index_dir
        index_list = "%s/index/list" % self.index_dir
        if not os.path.exists(index_dir):
            os.makedirs(index_dir)
        if not os.path.exists(index_list):
            os.makedirs(index_list)
        self.create_index_file()

    def create_index_file(self):
        file_count = self.index_file_max % self.single_file
        for i in range(0, file_count):
            index_file = "%s/index_%d.ix" % (self.index_dir, i)
            if not os.path.isfile(index_file):
                with open(index_file, "a+") as fp:
                    fp.write(chr(0) * self.single_file)

    def add(self, key, encode="utf-8"):
        key_bytes = key.encode(encode)
        key_num = 1
        for b in key_bytes:
            key_num *= b
        index_key = key_num % self.index_file_max


class CacheBase:
    def __init__(self, cache_dir, data_file_num=2, data_file_max=65535):
        self.cache_dir = cache_dir
        self.data_file_max = data_file_max
        # self.file_cache: list = [queue.Queue()] * file_max
        # self.cache_queue = queue.Queue()
        self.data_file = queue.Queue()
        self.data_file_num = data_file_num
        self.init()

    def init(self):
        data_dir = "%s/data" % self.cache_dir
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)
        self.create_data_file()

    def create_data_file(self):
        for i in range(0, self.data_file_num):
            self.data_file_num += 1
            self.data_file.put(FileOpt(path=self.cache_dir, num=self.data_file_num, prefix="data", ext="dat"))

    def get_data_file(self):
        while self.data_file.empty():
            pass
        fs = self.data_file.put()
        if fs.tell() > self.data_file_max:
            fs.flush()
            fs.close()
            self.data_file_num += 1
            fs = FileOpt(path=self.cache_dir, num=self.data_file_num, prefix="data", ext="dat")
        return fs

    def append(self, data):
        num, start, end = self.add_data(data)

    def add_data(self, data):
        fs = self.get_data_file()
        fs_start = fs.tell()
        fs.write(data)
        fs_end = fs.tell()
        self.data_file.put(fs)
        return fs.num, fs_start, fs_end

    # def append(self, key, val, encode="utf-8"):
    #     data_bytes = key.encode(encode)
    #     data_num = 0
    #     for data in data_bytes:
    #         data_num += data
    #     self.cache_queue.put({"file": data_num, "key": key, "data": val})
    #     # self.file_cache[data_num % len(self.file_cache)].put({"key": data_num, "data": val})
    #
    # def add_cache(self):
    #     if not self.cache_queue.empty():
    #         data_item = self.cache_queue.get()
    #         with open("%s/%d.ce" % (self.cache_dir, data_item["file"]), "a+") as fp:
    #             json_str = json.dumps(data_item)
    #             fp.write(json_str + "\n")
    #             fp.flush()

    # def create_index(self):
    #     pass
    #
    # def read(self):
    #     pass

